﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.IO;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Configuration;
using System.Web.Security;
using System.Security.Principal;
using System.Threading;

namespace HIS {

    public partial class Moduleinvoker : System.Web.UI.Page {

        #region Fields
        private object objinstant = null;
        private string strPar1 = null;
        private string strPar2 = null;
        private string strPar3 = null;
        private string strPar4 = null;
        private string strMethod = "index";
        private string strAssemblyName = string.Empty;
        private Type type = null;
        private string[] arrUserRole = null;
        private string userRole = string.Empty;
        #endregion

        protected void Page_Load(object sender, EventArgs e) {
            try {
                SetPrincipal();

                Assembly currentAssembly = Assembly.GetExecutingAssembly();
                string ss = currentAssembly.Location;
                Type[] types = currentAssembly.GetTypes();

                SetVariable(types);

                if (objinstant == null) objinstant = Activator.CreateInstance(type);

                Type temp = objinstant.GetType();
                MethodInfo[] methodInfos = temp.GetMethods(BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance);
                if (strMethod == string.Empty) strMethod = "index";
                MethodInfo methodInfo = Array.Find(methodInfos, element => element.Name.ToLower() == strMethod);
                
                ValidateUserTryInvokeMethod(methodInfo);

                string InnerException = string.Empty;
                try {
                    type.InvokeMember(methodInfo.Name, BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.Public, null, objinstant, null);
                } catch (TargetInvocationException exReflection) {
                    InnerException = exReflection.InnerException.Message;
                }

            } catch (Exception ex) {
                Response.Write(ex.Message);
            } finally {
                objinstant = null;
            }
            
        }

        private void SetVariable(Type[] types) {
            try {
                strPar1 = Page.RouteData.Values["par1"] as string;
                strPar2 = Page.RouteData.Values["par2"] as string;
                strPar3 = Page.RouteData.Values["par3"] as string;
                strPar4 = Page.RouteData.Values["par4"] as string;

                string stringLast = string.Empty;
                string strPath = string.Empty;
                string strParName = string.Empty;

                for (int i = 0; i < Page.RouteData.Values.Count; i++) {
                    strParName = "par" + (i + 1).ToString();
                    stringLast = Page.RouteData.Values[strParName] == null ? string.Empty : Page.RouteData.Values[strParName] as string;
                    strAssemblyName += Page.RouteData.Values[strParName] == null ? string.Empty : "." + Page.RouteData.Values[strParName];
                    strPath += Page.RouteData.Values[strParName] == null ? string.Empty : "\\" + Page.RouteData.Values[strParName];
                }

                bool IsDirectory = Directory.Exists(Request.PhysicalApplicationPath + "views" + strPath);

                if (IsDirectory) {
                    strAssemblyName = ".controllers" + strAssemblyName + ".default";
                    strMethod = "index";

                    if (strAssemblyName == ".controllers.default") {
                        strAssemblyName = ".controllers.home.default";
                    }
                    type = Array.Find(types, element => element.FullName.ToLower() == "his" + strAssemblyName);
                    return;
                } else {
                    strAssemblyName = ".controllers" + strAssemblyName;
                    type = Array.Find(types, element => element.FullName.ToLower() == "his" + strAssemblyName);

                    if (type != null) {
                        strMethod = "index";
                    } else {
                        strAssemblyName = strAssemblyName.Replace('.' + stringLast, string.Empty);
                        type = Array.Find(types, element => element.FullName.ToLower() == "his" + strAssemblyName);
                        strMethod = stringLast;
                    }
                }
            } catch { }

        }

        private void SetPrincipal() {
            string encryptedTicket = string.Empty;
            try {
                encryptedTicket = KeanuMvc.Reference.CryptoString.Decrypt(HttpContext.Current.Session["userticketdata"].ToString());
            } catch { }

            if (encryptedTicket == string.Empty) {
                //if (!Request.RawUrl.ToLower().Contains("home/default/login/")) Response.Redirect(ConfigurationManager.AppSettings["rooturl"] + "home/default/login/");
                if (
                    !Request.RawUrl.ToLower().Contains("home/default/logoutacc/") &&
                    !Request.RawUrl.ToLower().Contains("home/default/logoutaccajax/") &&
                    !Request.RawUrl.ToLower().Contains("home/default/login/")
                    ) {
                    if (Request.RawUrl.ToLower() == "/") {
                        Response.Redirect("/home/default/login/");
                        return;
                    }
                    if ((HttpContext.Current.Request["X-Requested-With"] == "XMLHttpRequest") || ((HttpContext.Current.Request.Headers != null) && (HttpContext.Current.Request.Headers["X-Requested-With"] == "XMLHttpRequest"))) {
                        Response.Redirect("/home/default/logoutaccajax/");
                    } else {
                        Response.Redirect("/home/default/logoutacc/");
                    }
                    
                }
              
            } else {
                string decryptUserId = encryptedTicket.Split('|')[0];
                userRole = encryptedTicket.Split('|')[1];
                arrUserRole = userRole.Split(';');

                GenericIdentity userIdentity = new GenericIdentity(decryptUserId);
                GenericPrincipal userPrincipal = new GenericPrincipal(userIdentity, arrUserRole);
                HttpContext.Current.User = userPrincipal;
                Thread.CurrentPrincipal = HttpContext.Current.User;
            }
        }

        private void ValidateUserTryInvokeMethod(MethodInfo methodInfo) {
            object[] customAttributes = methodInfo.GetCustomAttributes(typeof(HIS.Utils.Securities.Authorization), false);
            HIS.Utils.Securities.Authorization foundAttribute = null;
            try {
                foundAttribute = (HIS.Utils.Securities.Authorization)customAttributes[0];
                if (foundAttribute.RoleAction == "all") return;
                if (userRole != string.Empty) {
                    if (userRole == "0") return;

                    string filePath = HttpContext.Current.Request.PhysicalApplicationPath + "Cache\\RoleAction\\" + userRole + ".txt";
                    string[] roleaction = File.ReadAllLines(filePath);
                    if (Array.IndexOf(roleaction, foundAttribute.RoleAction) < 0) {
                        Response.Redirect(ConfigurationManager.AppSettings["rooturl"] + "home/default/unauthorize/");
                    }
                }
            } catch {
                Response.Redirect(ConfigurationManager.AppSettings["rooturl"] + "home/default/unauthorize/");
            }
            
        }
    }
}